/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Search;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.MultiLineString;
import com.vividsolutions.jts.geom.Point;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;
import org.geotools.data.FileDataStore;
import org.geotools.data.FileDataStoreFinder;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.feature.FeatureIterator;
import org.geotools.graph.path.DijkstraShortestPathFinder;
import org.geotools.graph.path.Path;
import org.geotools.graph.structure.Edge;
import org.geotools.graph.structure.Graph;
import org.geotools.graph.structure.GraphVisitor;
import org.geotools.graph.structure.Graphable;
import org.geotools.graph.structure.Node;
import org.geotools.graph.traverse.GraphIterator;
import org.geotools.graph.traverse.GraphTraversal;
import org.geotools.graph.traverse.basic.AbstractGraphIterator;
import org.geotools.graph.traverse.basic.BasicGraphTraversal;
import org.geotools.graph.traverse.basic.CountingWalker;
import org.geotools.graph.traverse.basic.SimpleGraphWalker;
import org.geotools.graph.traverse.standard.BreadthFirstIterator;
import org.geotools.graph.traverse.standard.DepthFirstIterator;
import org.geotools.graph.traverse.standard.DijkstraIterator;
import org.geotools.swing.data.JFileDataStoreChooser;
import org.opengis.feature.Feature;
import org.opengis.feature.Property;
import org.opengis.feature.simple.SimpleFeature;

/**
 *
 * @author oleg
 */
public class MySearch {

    Coordinate[] points;
    int searchType; // 0 - with minimum signal intersections
    // 1 - maximizing average speed
    // 2 - with direction

    public MySearch(int searchType) throws IOException {
        int kol = 0;
        this.searchType = searchType;
        File file = new File("improvedmap/signals0.01.shp");
        FileDataStore store = FileDataStoreFinder.getDataStore(file);
        SimpleFeatureSource featureSource = store.getFeatureSource();
        SimpleFeatureCollection features = featureSource.getFeatures();
        points = new Coordinate[features.size()];
        FeatureIterator iter = features.features();

        while (iter.hasNext()) {
            SimpleFeature feature = (SimpleFeature) iter.next();
            Geometry geom = (Point) feature.getDefaultGeometry();
            Coordinate point = geom.getCoordinate();
            points[kol] = new Coordinate(point);
            if (dotsAreClose(point, 347973, 6110531, 3)) {
                System.out.println("finded");
            }
            kol++;
        }
        iter.close();

    }

    private boolean dotsAreClose(Coordinate c, double x, double y, double e) {
        if ((c.x < x + e) && (c.x > x - e) && (c.y < y + e) && (c.y > y - e)) {
            return true;
        }
        return false;
    }
    static int k = 0;

    public Path search(Graph graph, Node start, Node finish) {

        DijkstraIterator.NodeWeighter nodeWeighter = null;
        DijkstraIterator.EdgeWeighter weighter = null;

        if (searchType == 1) {
            nodeWeighter =  new DijkstraIterator.NodeWeighter() {

                public double getWeight(Node n, Edge e1, Edge e2) {
                    Point object = (Point) n.getObject();
                    Coordinate coordinate = object.getCoordinate();
                    for (int i = 0; i < points.length; i++) {
                        if ((points[i].x == coordinate.x) && (points[i].y == coordinate.y)) {
                            k++;
                            return 30000;
                        }
                    }
                    return 3;
                }
            };

            weighter = new DijkstraIterator.EdgeWeighter() {

                public double getWeight(Edge e) {
                    SimpleFeature feature = (SimpleFeature) e.getObject();
                    Geometry geometry = (Geometry) feature.getDefaultGeometry();
                    /*
                    Collection<Property> properties = feature.getProperties();
                    Iterator<Property> iterator = properties.iterator();
                    while(iterator.hasNext()){
                        Property next = iterator.next();
                        System.out.println(next.getName()+":"+next.getValue());
                    }
                     * 
                     */
                    /*
                    Node nodeA = e.getNodeA();
                    Node nodeB = e.getNodeB();
                    Point pointA=(Point) nodeA.getObject();
                    Point pointB=(Point) nodeB.getObject();
                    for(int i=0;i<points.length;i++){
                    if(pointA.getCoordinate().x == points[i].x && pointA.getCoordinate().y == points[i].y){
                    return 10000;
                    }
                    if(pointB.getCoordinate().x == points[i].x && pointB.getCoordinate().y == points[i].y){
                    return 10000;
                    }
                    }
                     *
                     */
                    return geometry.getLength();
                }
            };
        }
        else if(searchType==2){ //алгоритм по среднему времени
            nodeWeighter =  new DijkstraIterator.NodeWeighter() {

                public double getWeight(Node n, Edge e1, Edge e2) {
                    Point object = (Point) n.getObject();
                    Coordinate coordinate = object.getCoordinate();
                    for (int i = 0; i < points.length; i++) {
                        if ((points[i].x == coordinate.x) && (points[i].y == coordinate.y)) {
                            k++;
                            return 200;
                        }
                    }
                    return 3;
                }
            };

            weighter = new DijkstraIterator.EdgeWeighter() {

                public double getWeight(Edge e) {
                    SimpleFeature feature = (SimpleFeature) e.getObject();
                    Geometry geometry = (Geometry) feature.getDefaultGeometry();
                    Property property = feature.getProperty("TYPE");
                    if(((String) property.getValue()) == null ? "3" == null : ((String) property.getValue()).equals("3")){
                        return geometry.getLength()*3.5;
                    }
                    
                    return geometry.getLength();
                }
            };
        }
        Search.DijkstraIterator mdi = new Search.DijkstraIterator(weighter, nodeWeighter);
        mdi.setSource(start);
        Search.DijkstraShortestPathFinder pf2 = new Search.DijkstraShortestPathFinder(graph, mdi);
        pf2.calculate();

        Path path = pf2.getPath(finish);
        Iterator iterator = path.iterator();
        while (iterator.hasNext()) {
            Graphable g = (Graphable) iterator.next();
            System.out.println("(" + ((Point) (g.getObject())).getCoordinate().x + ";" + ((Point) (g.getObject())).getCoordinate().y + "),   " + g.getObject().getClass().toString());
        }
        return path;
    }
}
